
//给定一个文本文件，其中相同字符的序列多次相邻出现，将其转换为另一个文本文件，其中某些字符出现的频率比其他字符高得多。
import edu.princeton.cs.algs4.BinaryStdIn;
import edu.princeton.cs.algs4.BinaryStdOut;
import java.util.LinkedList;

public class MoveToFront {
  // apply move-to-front encoding, reading from standard input and writing to
  // standard output
  // 维护一个由 256 个扩展 ASCII 字符组成的有序序列。通过使序列中的第 i个字符等于第 i个扩展 ASCII 字符来初始化该序列。
  // 现在，从标准输入中逐个读取 8 位字符c；输出该字符在序列中c出现的 8 位索引；然后移至c前端。
  // 用链表结构
  public static void encode() {
    int R = 256;
    LinkedList<Character> ascii = new LinkedList<Character>();
    for (int i = 0; i < R; i++) {
      ascii.add(i, (char) i);
    }
    while (!BinaryStdIn.isEmpty()) {
      char read = BinaryStdIn.readChar();
      int indexOfRead = ascii.indexOf(read);
      BinaryStdOut.write((char)indexOfRead);
      ascii.remove(indexOfRead);
      ascii.addFirst(read);
    }
    BinaryStdOut.close();
  }

  // apply move-to-front decoding, reading from standard input and writing to
  // standard output
  // 初始化一个包含 256 个字符的有序序列，其中扩展 ASCII 字符 i出现在序列中的第 i 个位置。现在， 从标准输入中逐个读取每个 8 位字符i
  // （但将其视为 0 到 255 之间的整数）；
  // 将第 i个字符写入序列中；并将该字符移至前端。检查解码器是否恢复了任何编码消息。
  public static void decode() {
    int R = 256;
    LinkedList<Character> ascii = new LinkedList<Character>();
    for (int i = 0; i < R; i++) {
      ascii.add(i, (char) i);
    }
    while (!BinaryStdIn.isEmpty()) {
      char read = BinaryStdIn.readChar();
      char readchar=ascii.get(read);
      BinaryStdOut.write(readchar);
      ascii.remove(read);
      ascii.addFirst(readchar);
    }
    BinaryStdOut.close();
  }

  // if args[0] is "-", apply move-to-front encoding
  // if args[0] is "+", apply move-to-front decoding
  public static void main(String[] args) {
    if(args[0].equals("+"))
    {
      decode();
    }
    else
    {
      encode();
    }
  }
}
